//***************************************************************************
//   Copyright(c)2022, Xidian University D405.
//   All rights reserved
//
//   IP Name         :   Null
//   File name       :   np_dma_pending_cnt.v
//   Module name     :   np_dma_pending_cnt
//   Author          :   Wang Zekun
//   Date            :   2022/04/23
//   Version         :   v1.0
//   Verison History :   v1.0
//   Edited by       :   Wang Zekun
//   Modification history : v1.0 
//
// ----------------------------------------------------------------------------
// Version 1.0      Date(2022/04/23)
// Abstract : rx fifo empty for a long time,as timeout,need to count to pending out
//-----------------------------------------------------------------------------
// Programmer's model
//                    Null
//-----------------------------------------------------------------------------
//interface list :
//                Null
module np_dma_pending_cnt (
  input  wire                               clk_i,
  input  wire                               resetn_i,
  input  wire                               load_en_i,
  input  wire [31 : 0]                      load_pending_time_i,
  input  wire                               pending_en_i,
  input  wire                               cnt_en_i,

  output wire                               cnt_stop_o
);
  
  reg  [31 : 0]            down_count;
  wire [31 : 0]            down_count_next;
  reg                      cnt_en;

  always @(posedge clk_i or negedge resetn_i) begin
    if(~resetn_i) begin
      down_count <= {32{1'b1}};
    end
    else if (load_en_i | cnt_stop_o | ~cnt_en_i)begin
      down_count <= load_pending_time_i;
    end
    else if (cnt_en)begin
      down_count <= down_count_next;
    end
    else begin
      down_count <= load_pending_time_i;
    end
  end

  always @(posedge clk_i or negedge resetn_i) begin
    if(~resetn_i) begin
      cnt_en <= 1'b0;
    end
    else if (pending_en_i)begin
      cnt_en <= 1'b1;
    end
    else if (cnt_stop_o)begin
      cnt_en <= 1'b0;
    end
    else begin
      cnt_en <= cnt_en;
    end
  end

  assign down_count_next = down_count - 1'b1;
  assign cnt_stop_o = ~(|down_count);

endmodule